<!DOCTYPE html>
<html lang=zh>
<head>
    <meta charset="utf-8">
    
    <title>第四十六章：SpringBoot &amp; RabbitMQ完成消息延迟消费 | 恒宇少年De成长之路</title>
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1" />
    <meta name="description" content="在2018-3-1日SpringBoot官方发版了2.0.0.RELEASE最新版本，新版本完全基于Spring5.0来构建，JDK最低支持也从原来的1.6也改成了1.8，不再兼容1.8以下的版本，更多新特性请查看官方文档。">
<meta name="keywords" content="SpringBoot">
<meta property="og:type" content="article">
<meta property="og:title" content="第四十六章：SpringBoot &amp; RabbitMQ完成消息延迟消费">
<meta property="og:url" content="http://blog.yuqiyu.com/spring-boot-chapter-46/index.html">
<meta property="og:site_name" content="恒宇少年De成长之路">
<meta property="og:description" content="在2018-3-1日SpringBoot官方发版了2.0.0.RELEASE最新版本，新版本完全基于Spring5.0来构建，JDK最低支持也从原来的1.6也改成了1.8，不再兼容1.8以下的版本，更多新特性请查看官方文档。">
<meta property="og:locale" content="zh-CN">
<meta property="og:image" content="http://upload-images.jianshu.io/upload_images/4461954-456e709d038bfd7a.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240">
<meta property="og:image" content="http://upload-images.jianshu.io/upload_images/4461954-d80b777ca38632ba.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240">
<meta property="og:updated_time" content="2018-03-04T04:48:17.977Z">
<meta name="twitter:card" content="summary">
<meta name="twitter:title" content="第四十六章：SpringBoot &amp; RabbitMQ完成消息延迟消费">
<meta name="twitter:description" content="在2018-3-1日SpringBoot官方发版了2.0.0.RELEASE最新版本，新版本完全基于Spring5.0来构建，JDK最低支持也从原来的1.6也改成了1.8，不再兼容1.8以下的版本，更多新特性请查看官方文档。">
<meta name="twitter:image" content="http://upload-images.jianshu.io/upload_images/4461954-456e709d038bfd7a.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240">
    

    
        <link rel="alternate" href="/" title="恒宇少年De成长之路" type="application/atom+xml" />
    

    

    <link rel="stylesheet" href="/libs/font-awesome/css/font-awesome.min.css">
    <link rel="stylesheet" href="/libs/open-sans/styles.css">
    <link rel="stylesheet" href="/libs/source-code-pro/styles.css">

    <link rel="stylesheet" href="/css/style.css">

    <script src="/libs/jquery/2.1.3/jquery.min.js"></script>
    
    
        <link rel="stylesheet" href="/libs/lightgallery/css/lightgallery.min.css">
    
    
        <link rel="stylesheet" href="/libs/justified-gallery/justifiedGallery.min.css">
    
    
    
    


</head>

<body>
    <div id="container">
        <header id="header">
    <div id="header-main" class="header-inner">
        <div class="outer">
            <a href="/" id="logo">
                <i class="logo"></i>
                <span class="site-title">恒宇少年De成长之路</span>
            </a>
            <nav id="main-nav">
                
                    <a class="main-nav-link" href="/.">首页</a>
                
                    <a class="main-nav-link" href="/archives">时间轴</a>
                
                    <a class="main-nav-link" href="/categories">文章专题</a>
                
                    <a class="main-nav-link" href="/tags">标签云</a>
                
                    <a class="main-nav-link" href="/about">关于我</a>
                
            </nav>
            
                
                <nav id="sub-nav">
                    <div class="profile" id="profile-nav">
                        <a id="profile-anchor" href="javascript:;">
                            <img class="avatar" src="/css/images/avatar.png" />
                            <i class="fa fa-caret-down"></i>
                        </a>
                    </div>
                </nav>
            
            <div id="search-form-wrap">

    <form class="search-form">
        <input type="text" class="ins-search-input search-form-input" placeholder="搜索" />
        <!--button type="submit" class="search-form-submit"></button-->
    </form>
    <div class="ins-search">
    <div class="ins-search-mask"></div>
    <div class="ins-search-container">
        <div class="ins-input-wrapper">
            <input type="text" class="ins-search-input" placeholder="想要查找什么..." />
            <span class="ins-close ins-selectable"><i class="fa fa-times-circle"></i></span>
        </div>
        <div class="ins-section-wrapper">
            <div class="ins-section-container"></div>
        </div>
    </div>
</div>
<script>
(function (window) {
    var INSIGHT_CONFIG = {
        TRANSLATION: {
            POSTS: '文章',
            PAGES: '页面',
            CATEGORIES: '分类',
            TAGS: '标签',
            UNTITLED: '(未命名)',
        },
        ROOT_URL: '/',
        CONTENT_URL: '/content.json',
    };
    window.INSIGHT_CONFIG = INSIGHT_CONFIG;
})(window);
</script>
<script src="/js/insight.js"></script>

</div>
        </div>
    </div>
    <div id="main-nav-mobile" class="header-sub header-inner">
        <table class="menu outer">
            <tr>
                
                    <td ><a  class="main-nav-link" href="/.">首页</a></td>
                
                    <td ><a  class="main-nav-link" href="/archives">时间轴</a></td>
                
                    <td ><a  class="main-nav-link" href="/categories">文章专题</a></td>
                
                    <td ><a  class="main-nav-link" href="/tags">标签云</a></td>
                
                    <td ><a  class="main-nav-link" href="/about">关于我</a></td>
                
                <td>
                    
    <div class="search-form">
        <input type="text" class="ins-search-input search-form-input" placeholder="搜索" />
    </div>

                </td>
            </tr>
        </table>
    </div>
</header>

        <div class="outer">
            
                

<aside id="profile">
    <div class="inner profile-inner">
        <div class="base-info profile-block">
            <img id="avatar" src="/css/images/avatar.png" />
            <h2 id="name">恒宇少年</h2>
            <h3 id="title">Java软件工程师 &amp; 程序猿</h3>
            <span id="location"><i class="fa fa-map-marker"></i>山东, 济南</span>
            <a id="follow" target="_blank" href="https://www.jianshu.com/u/092df3f77bca">关注我</a>
        </div>
        <div class="article-info profile-block">
            <div class="article-info-block">
                43
                <span>文章</span>
            </div>
            <div class="article-info-block">
                2
                <span>标签</span>
            </div>
        </div>
        
        <div class="profile-block social-links">
            <table>
                <tr>
                    
                    
                    <td>
                        <a href="http://github.com/ppoffice/hexo-theme-icarus" target="_blank" title="github" class=tooltip>
                            <i class="fa fa-github"></i>
                        </a>
                    </td>
                    
                    <td>
                        <a href="/" target="_blank" title="twitter" class=tooltip>
                            <i class="fa fa-twitter"></i>
                        </a>
                    </td>
                    
                    <td>
                        <a href="/" target="_blank" title="facebook" class=tooltip>
                            <i class="fa fa-facebook"></i>
                        </a>
                    </td>
                    
                    <td>
                        <a href="/" target="_blank" title="dribbble" class=tooltip>
                            <i class="fa fa-dribbble"></i>
                        </a>
                    </td>
                    
                    <td>
                        <a href="/" target="_blank" title="rss" class=tooltip>
                            <i class="fa fa-rss"></i>
                        </a>
                    </td>
                    
                </tr>
            </table>
        </div>
        
    </div>
</aside>

            
            <section id="main"><article id="post-spring-boot-chapter-46" class="article article-type-post" itemscope itemprop="blogPost">
    <div class="article-inner">
        
        
            <header class="article-header">
                
    
        <h1 class="article-title" itemprop="name">
            第四十六章：SpringBoot &amp; RabbitMQ完成消息延迟消费
        </h1>
    

                
                    <div class="article-meta">
                        
    <div class="article-date">
        <i class="fa fa-calendar"></i>
        <a href="/spring-boot-chapter-46/">
            <time datetime="2018-03-03T16:00:00.000Z" itemprop="datePublished">2018-03-04</time>
        </a>
    </div>


                        
    <div class="article-category">
    	<i class="fa fa-folder"></i>
        <a class="article-category-link" href="/categories/SpringBoot-核心技术/">SpringBoot 核心技术</a>
    </div>

                        
    <div class="article-tag">
        <i class="fa fa-tag"></i>
        <a class="tag-link" href="/tags/SpringBoot/">SpringBoot</a>
    </div>

                    </div>
                
            </header>
        
        
        <div class="article-entry" itemprop="articleBody">
        
            
            <p>在<code>2018-3-1</code>日<code>SpringBoot</code>官方发版了<code>2.0.0.RELEASE</code>最新版本，新版本完全基于<code>Spring5.0</code>来构建，<code>JDK</code>最低支持也从原来的<code>1.6</code>也改成了<code>1.8</code>，不再兼容<code>1.8</code>以下的版本，更多新特性请查看<a href="https://docs.spring.io/spring-boot/docs/2.0.0.RELEASE/reference/htmlsingle/" target="_blank" rel="noopener">官方文档</a>。<br><a id="more"></a></p>
<h1 id="本章目标"><a href="#本章目标" class="headerlink" title="本章目标"></a>本章目标</h1><p>基于<code>SpringBoot</code>整合<code>RabbitMQ</code>完成消息延迟消费。</p>
<h1 id="构建项目"><a href="#构建项目" class="headerlink" title="构建项目"></a>构建项目</h1><h4 id="注意前言"><a href="#注意前言" class="headerlink" title="注意前言"></a>注意前言</h4><blockquote>
<p>由于<code>SpringBoot</code>的内置扫描机制，我们如果不自动配置扫描路径，请保持下面<code>rabbitmq-common</code>模块内的配置可以被<code>SpringBoot</code>扫描到，否则不会自动创建队列，控制台会输出404的错误信息。</p>
</blockquote>
<h1 id="SpringBoot-企业级核心技术学习专题"><a href="#SpringBoot-企业级核心技术学习专题" class="headerlink" title="SpringBoot 企业级核心技术学习专题"></a>SpringBoot 企业级核心技术学习专题</h1><table>
<thead>
<tr>
<th style="text-align:center">专题</th>
<th style="text-align:left">专题名称</th>
<th style="text-align:left">专题描述</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:center">001</td>
<td style="text-align:left"><a href="http://www.jianshu.com/c/3f69deddbed3" target="_blank" rel="noopener">Spring Boot 核心技术</a></td>
<td style="text-align:left">讲解SpringBoot一些企业级层面的核心组件</td>
</tr>
<tr>
<td style="text-align:center">002</td>
<td style="text-align:left"><a href="https://gitee.com/hengboy/spring-boot-chapter" target="_blank" rel="noopener">Spring Boot 核心技术章节源码</a></td>
<td style="text-align:left">Spring Boot 核心技术简书每一篇文章码云对应源码</td>
</tr>
<tr>
<td style="text-align:center">003</td>
<td style="text-align:left"><a href="http://www.jianshu.com/c/1faac22666e7" target="_blank" rel="noopener">Spring Cloud 核心技术</a></td>
<td style="text-align:left">对Spring Cloud核心技术全面讲解</td>
</tr>
<tr>
<td style="text-align:center">004</td>
<td style="text-align:left"><a href="https://gitee.com/hengboy/spring-cloud-chapter" target="_blank" rel="noopener">Spring Cloud 核心技术章节源码</a></td>
<td style="text-align:left">Spring Cloud 核心技术简书每一篇文章对应源码</td>
</tr>
<tr>
<td style="text-align:center">005</td>
<td style="text-align:left"><a href="http://www.jianshu.com/c/ab4789177827" target="_blank" rel="noopener">QueryDSL 核心技术</a></td>
<td style="text-align:left">全面讲解QueryDSL核心技术以及基于SpringBoot整合SpringDataJPA</td>
</tr>
<tr>
<td style="text-align:center">006</td>
<td style="text-align:left"><a href="http://www.jianshu.com/c/f1b269bb2fd6" target="_blank" rel="noopener">SpringDataJPA 核心技术</a></td>
<td style="text-align:left">全面讲解SpringDataJPA核心技术</td>
</tr>
</tbody>
</table>
<p>我们本章采用<code>2.0.0.RELEASE</code>版本的<code>SpringBoot</code>，添加相关的依赖如下所示：<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br></pre></td><td class="code"><pre><span class="line">&lt;parent&gt;</span><br><span class="line">        &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;</span><br><span class="line">        &lt;artifactId&gt;spring-boot-starter-parent&lt;/artifactId&gt;</span><br><span class="line">        &lt;version&gt;2.0.0.RELEASE&lt;/version&gt;</span><br><span class="line">        &lt;relativePath/&gt; &lt;!-- lookup parent from repository --&gt;</span><br><span class="line">&lt;/parent&gt;</span><br><span class="line">......</span><br><span class="line">&lt;dependencies&gt;</span><br><span class="line">        &lt;!--rabbbitMQ相关依赖--&gt;</span><br><span class="line">        &lt;dependency&gt;</span><br><span class="line">            &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;</span><br><span class="line">            &lt;artifactId&gt;spring-boot-starter-amqp&lt;/artifactId&gt;</span><br><span class="line">        &lt;/dependency&gt;</span><br><span class="line">        &lt;!--web相关依赖--&gt;</span><br><span class="line">        &lt;dependency&gt;</span><br><span class="line">            &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;</span><br><span class="line">            &lt;artifactId&gt;spring-boot-starter-web&lt;/artifactId&gt;</span><br><span class="line">        &lt;/dependency&gt;</span><br><span class="line">        &lt;!--lombok依赖--&gt;</span><br><span class="line">        &lt;dependency&gt;</span><br><span class="line">            &lt;groupId&gt;org.projectlombok&lt;/groupId&gt;</span><br><span class="line">            &lt;artifactId&gt;lombok&lt;/artifactId&gt;</span><br><span class="line">            &lt;optional&gt;true&lt;/optional&gt;</span><br><span class="line">        &lt;/dependency&gt;</span><br><span class="line">        &lt;!--spring boot tester--&gt;</span><br><span class="line">        &lt;dependency&gt;</span><br><span class="line">            &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;</span><br><span class="line">            &lt;artifactId&gt;spring-boot-starter-test&lt;/artifactId&gt;</span><br><span class="line">            &lt;scope&gt;test&lt;/scope&gt;</span><br><span class="line">        &lt;/dependency&gt;</span><br><span class="line">        &lt;!--fast json依赖--&gt;</span><br><span class="line">        &lt;dependency&gt;</span><br><span class="line">            &lt;groupId&gt;com.alibaba&lt;/groupId&gt;</span><br><span class="line">            &lt;artifactId&gt;fastjson&lt;/artifactId&gt;</span><br><span class="line">            &lt;version&gt;1.2.40&lt;/version&gt;</span><br><span class="line">        &lt;/dependency&gt;</span><br><span class="line">    &lt;/dependencies&gt;</span><br><span class="line">......</span><br></pre></td></tr></table></figure></p>
<p>我们仍然采用多模块的方式来测试队列的<code>Provider</code>以及<code>Consumer</code>。</p>
<h3 id="队列公共模块"><a href="#队列公共模块" class="headerlink" title="队列公共模块"></a>队列公共模块</h3><p>我们先来创建一个名为<code>rabbitmq-common</code>公共依赖模块（Create New Maven Module）<br>在公共模块内添加一个<code>QueueEnum</code>队列枚举配置，该枚举内配置队列的<code>Exchange</code>、<code>QueueName</code>、<code>RouteKey</code>等相关内容，如下所示：<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br></pre></td><td class="code"><pre><span class="line">package com.hengyu.rabbitmq.lazy.enums;</span><br><span class="line"></span><br><span class="line">import lombok.Getter;</span><br><span class="line"></span><br><span class="line">/**</span><br><span class="line"> * 消息队列枚举配置</span><br><span class="line"> *</span><br><span class="line"> * @author：于起宇 &lt;br/&gt;</span><br><span class="line"> * ===============================</span><br><span class="line"> * Created with IDEA.</span><br><span class="line"> * Date：2018/3/3</span><br><span class="line"> * Time：下午4:33</span><br><span class="line"> * 简书：http://www.jianshu.com/u/092df3f77bca</span><br><span class="line"> * ================================</span><br><span class="line"> */</span><br><span class="line">@Getter</span><br><span class="line">public enum QueueEnum &#123;</span><br><span class="line">    /**</span><br><span class="line">     * 消息通知队列</span><br><span class="line">     */</span><br><span class="line">    MESSAGE_QUEUE(&quot;message.center.direct&quot;, &quot;message.center.create&quot;, &quot;message.center.create&quot;),</span><br><span class="line">    /**</span><br><span class="line">     * 消息通知ttl队列</span><br><span class="line">     */</span><br><span class="line">    MESSAGE_TTL_QUEUE(&quot;message.center.topic.ttl&quot;, &quot;message.center.create.ttl&quot;, &quot;message.center.create.ttl&quot;);</span><br><span class="line">    /**</span><br><span class="line">     * 交换名称</span><br><span class="line">     */</span><br><span class="line">    private String exchange;</span><br><span class="line">    /**</span><br><span class="line">     * 队列名称</span><br><span class="line">     */</span><br><span class="line">    private String name;</span><br><span class="line">    /**</span><br><span class="line">     * 路由键</span><br><span class="line">     */</span><br><span class="line">    private String routeKey;</span><br><span class="line"></span><br><span class="line">    QueueEnum(String exchange, String name, String routeKey) &#123;</span><br><span class="line">        this.exchange = exchange;</span><br><span class="line">        this.name = name;</span><br><span class="line">        this.routeKey = routeKey;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></p>
<p>可以看到<code>MESSAGE_QUEUE</code>队列配置跟我们之前章节的配置一样，而我们另外新创建了一个后缀为<code>ttl</code>的消息队列配置。我们采用的这种方式是<code>RabbitMQ</code>消息队列其中一种的延迟消费模块，通过配置队列消息过期后转发的形式。</p>
<blockquote>
<p>这种模式比较简单，我们需要将消息先发送到<code>ttl</code>延迟队列内，当消息到达过期时间后会自动转发到<code>ttl</code>队列内配置的转发<code>Exchange</code>以及<code>RouteKey</code>绑定的队列内完成消息消费。</p>
</blockquote>
<p>下面我们来模拟<code>消息通知</code>的延迟消费场景，先来创建一个名为<code>MessageRabbitMqConfiguration</code>的队列配置类，该配置类内添加<code>消息通知队列</code>配置以及<code>消息通过延迟队列</code>配置，如下所示：<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br></pre></td><td class="code"><pre><span class="line">/**</span><br><span class="line"> * 消息通知 - 消息队列配置信息</span><br><span class="line"> *</span><br><span class="line"> * @author：恒宇少年 &lt;br/&gt;</span><br><span class="line"> * ===============================</span><br><span class="line"> * Created with IDEA.</span><br><span class="line"> * Date：2018/3/3</span><br><span class="line"> * Time：下午4:32</span><br><span class="line"> * 简书：http://www.jianshu.com/u/092df3f77bca</span><br><span class="line"> * ================================</span><br><span class="line"> */</span><br><span class="line">@Configuration</span><br><span class="line">public class MessageRabbitMqConfiguration &#123;</span><br><span class="line">    /**</span><br><span class="line">     * 消息中心实际消费队列交换配置</span><br><span class="line">     *</span><br><span class="line">     * @return</span><br><span class="line">     */</span><br><span class="line">    @Bean</span><br><span class="line">    DirectExchange messageDirect() &#123;</span><br><span class="line">        return (DirectExchange) ExchangeBuilder</span><br><span class="line">                .directExchange(QueueEnum.MESSAGE_QUEUE.getExchange())</span><br><span class="line">                .durable(true)</span><br><span class="line">                .build();</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    /**</span><br><span class="line">     * 消息中心延迟消费交换配置</span><br><span class="line">     *</span><br><span class="line">     * @return</span><br><span class="line">     */</span><br><span class="line">    @Bean</span><br><span class="line">    DirectExchange messageTtlDirect() &#123;</span><br><span class="line">        return (DirectExchange) ExchangeBuilder</span><br><span class="line">                .directExchange(QueueEnum.MESSAGE_TTL_QUEUE.getExchange())</span><br><span class="line">                .durable(true)</span><br><span class="line">                .build();</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    /**</span><br><span class="line">     * 消息中心实际消费队列配置</span><br><span class="line">     *</span><br><span class="line">     * @return</span><br><span class="line">     */</span><br><span class="line">    @Bean</span><br><span class="line">    public Queue messageQueue() &#123;</span><br><span class="line">        return new Queue(QueueEnum.MESSAGE_QUEUE.getName());</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">    /**</span><br><span class="line">     * 消息中心TTL队列</span><br><span class="line">     *</span><br><span class="line">     * @return</span><br><span class="line">     */</span><br><span class="line">    @Bean</span><br><span class="line">    Queue messageTtlQueue() &#123;</span><br><span class="line">        return QueueBuilder</span><br><span class="line">                .durable(QueueEnum.MESSAGE_TTL_QUEUE.getName())</span><br><span class="line">                // 配置到期后转发的交换</span><br><span class="line">                .withArgument(&quot;x-dead-letter-exchange&quot;, QueueEnum.MESSAGE_QUEUE.getExchange())</span><br><span class="line">                // 配置到期后转发的路由键</span><br><span class="line">                .withArgument(&quot;x-dead-letter-routing-key&quot;, QueueEnum.MESSAGE_QUEUE.getRouteKey())</span><br><span class="line">                .build();</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    /**</span><br><span class="line">     * 消息中心实际消息交换与队列绑定</span><br><span class="line">     *</span><br><span class="line">     * @param messageDirect 消息中心交换配置</span><br><span class="line">     * @param messageQueue  消息中心队列</span><br><span class="line">     * @return</span><br><span class="line">     */</span><br><span class="line">    @Bean</span><br><span class="line">    Binding messageBinding(DirectExchange messageDirect, Queue messageQueue) &#123;</span><br><span class="line">        return BindingBuilder</span><br><span class="line">                .bind(messageQueue)</span><br><span class="line">                .to(messageDirect)</span><br><span class="line">                .with(QueueEnum.MESSAGE_QUEUE.getRouteKey());</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    /**</span><br><span class="line">     * 消息中心TTL绑定实际消息中心实际消费交换机</span><br><span class="line">     *</span><br><span class="line">     * @param messageTtlQueue</span><br><span class="line">     * @param messageTtlDirect</span><br><span class="line">     * @return</span><br><span class="line">     */</span><br><span class="line">    @Bean</span><br><span class="line">    public Binding messageTtlBinding(Queue messageTtlQueue, DirectExchange messageTtlDirect) &#123;</span><br><span class="line">        return BindingBuilder</span><br><span class="line">                .bind(messageTtlQueue)</span><br><span class="line">                .to(messageTtlDirect)</span><br><span class="line">                .with(QueueEnum.MESSAGE_TTL_QUEUE.getRouteKey());</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></p>
<p>我们声明了<code>消息通知队列</code>的相关<code>Exchange</code>、<code>Queue</code>、<code>Binding</code>等配置，将<code>message.center.create</code>队列通过路由键<code>message.center.create</code>绑定到了<code>message.center.direct</code>交换上。</p>
<p>除此之外，我们还添加了<code>消息通知延迟队列</code>的<code>Exchange</code>、<code>Queue</code>、<code>Binding</code>等配置，将<code>message.center.create.ttl</code>队列通过<code>message.center.create.ttl</code>路由键绑定到了<code>message.center.topic.ttl</code>交换上。</p>
<p>我们仔细来看看<code>messageTtlQueue</code>延迟队列的配置，跟<code>messageQueue</code>队列配置不同的地方这里多出了<code>x-dead-letter-exchange</code>、<code>x-dead-letter-routing-key</code>两个参数，而这两个参数就是配置延迟队列过期后转发的<code>Exchange</code>、<code>RouteKey</code>，只要在创建队列时对应添加了这两个参数，在<code>RabbitMQ</code>管理平台看到的队列配置就不仅是单纯的<code>Direct</code>类型的队列类型，如下图所示：<br><img src="http://upload-images.jianshu.io/upload_images/4461954-456e709d038bfd7a.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt="队列类型差异"></p>
<p>在上图内我们可以看到<code>message.center.create.ttl</code>队列多出了<code>DLX</code>、<code>DLK</code>的配置，这就是<code>RabbitMQ</code>内<code>死信交换</code>的标志。<br>满足<code>死信交换</code>的条件，在官方文档中表示：</p>
<p>Messages from a queue can be ‘dead-lettered’; that is, republished to another exchange when any of the following events occur:</p>
<p>The message is rejected (basic.reject or basic.nack) with requeue=false,<br>The TTL for the message expires; or<br>The queue length limit is exceeded.</p>
<ul>
<li>该消息被拒绝（basic.reject或  basic.nack），requeue = false</li>
<li>消息的TTL过期</li>
<li>队列长度限制已超出<br><a href="https://www.rabbitmq.com/dlx.html" target="_blank" rel="noopener">官方文档地址</a></li>
</ul>
<p>我们需要满足上面的其中一种方式就可以了，我们采用满足第二个条件，采用过期的方式。</p>
<h3 id="队列消息提供者"><a href="#队列消息提供者" class="headerlink" title="队列消息提供者"></a>队列消息提供者</h3><p>我们再来创建一个名为<code>rabbitmq-lazy-provider</code>的模块(Create New Maven Module)，并且在<code>pom.xml</code>配置文件内添加<code>rabbitmq-common</code>模块的依赖，如下所示：<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">&lt;!--添加公共模块依赖--&gt;</span><br><span class="line">&lt;dependency&gt;</span><br><span class="line">      &lt;groupId&gt;com.hengyu&lt;/groupId&gt;</span><br><span class="line">      &lt;artifactId&gt;rabbitmq-common&lt;/artifactId&gt;</span><br><span class="line">      &lt;version&gt;0.0.1-SNAPSHOT&lt;/version&gt;</span><br><span class="line">&lt;/dependency&gt;</span><br></pre></td></tr></table></figure></p>
<h4 id="配置队列"><a href="#配置队列" class="headerlink" title="配置队列"></a>配置队列</h4><p>在<code>resource</code>下创建一个名为<code>application.yml</code>的配置文件，在该配置文件内添加如下配置信息：<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">spring:</span><br><span class="line">  #rabbitmq消息队列配置信息</span><br><span class="line">  rabbitmq:</span><br><span class="line">    host: localhost</span><br><span class="line">    port: 5672</span><br><span class="line">    username: guest</span><br><span class="line">    password: guest</span><br><span class="line">    virtual-host: /hengboy</span><br><span class="line">    publisher-confirms: true</span><br></pre></td></tr></table></figure></p>
<h4 id="消息提供者类"><a href="#消息提供者类" class="headerlink" title="消息提供者类"></a>消息提供者类</h4><p>接下来我们来创建名为<code>MessageProvider</code>消息提供者类，用来发送消息内容到消息通知延迟队列，代码如下所示：<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br></pre></td><td class="code"><pre><span class="line">/**</span><br><span class="line"> * 消息通知 - 提供者</span><br><span class="line"> *</span><br><span class="line"> * @author：于起宇 &lt;br/&gt;</span><br><span class="line"> * ===============================</span><br><span class="line"> * Created with IDEA.</span><br><span class="line"> * Date：2018/3/3</span><br><span class="line"> * Time：下午4:40</span><br><span class="line"> * 简书：http://www.jianshu.com/u/092df3f77bca</span><br><span class="line"> * ================================</span><br><span class="line"> */</span><br><span class="line">@Component</span><br><span class="line">public class MessageProvider &#123;</span><br><span class="line">    /**</span><br><span class="line">     * logger instance</span><br><span class="line">     */</span><br><span class="line">    static Logger logger = LoggerFactory.getLogger(MessageProvider.class);</span><br><span class="line">    /**</span><br><span class="line">     * RabbitMQ 模版消息实现类</span><br><span class="line">     */</span><br><span class="line">    @Autowired</span><br><span class="line">    private AmqpTemplate rabbitMqTemplate;</span><br><span class="line"></span><br><span class="line">    /**</span><br><span class="line">     * 发送延迟消息</span><br><span class="line">     *</span><br><span class="line">     * @param messageContent 消息内容</span><br><span class="line">     * @param exchange       队列交换</span><br><span class="line">     * @param routerKey      队列交换绑定的路由键</span><br><span class="line">     * @param delayTimes     延迟时长，单位：毫秒</span><br><span class="line">     */</span><br><span class="line">    public void sendMessage(Object messageContent, String exchange, String routerKey, final long delayTimes) &#123;</span><br><span class="line">        if (!StringUtils.isEmpty(exchange)) &#123;</span><br><span class="line">            logger.info(&quot;延迟：&#123;&#125;毫秒写入消息队列：&#123;&#125;，消息内容：&#123;&#125;&quot;, delayTimes, routerKey, JSON.toJSONString(messageContent));</span><br><span class="line">            // 执行发送消息到指定队列</span><br><span class="line">            rabbitMqTemplate.convertAndSend(exchange, routerKey, messageContent, message -&gt; &#123;</span><br><span class="line">                // 设置延迟毫秒值</span><br><span class="line">                message.getMessageProperties().setExpiration(String.valueOf(delayTimes));</span><br><span class="line">                return message;</span><br><span class="line">            &#125;);</span><br><span class="line">        &#125; else &#123;</span><br><span class="line">            logger.error(&quot;未找到队列消息：&#123;&#125;，所属的交换机&quot;, exchange);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></p>
<p>由于我们在  <code>pom.xml</code>配置文件内添加了<code>RabbitMQ</code>相关的依赖并且在上面<code>application.yml</code>文件内添加了对应的配置，<code>SpringBoot</code>为我们自动实例化了<code>AmqpTemplate</code>，该实例可以发送任何类型的消息到指定队列。<br>我们采用<code>convertAndSend</code>方法，将消息内容发送到指定<code>Exchange</code>、<code>RouterKey</code>队列，并且通过<code>setExpiration</code>方法设置过期时间，单位：毫秒。</p>
<h4 id="编写发送测试"><a href="#编写发送测试" class="headerlink" title="编写发送测试"></a>编写发送测试</h4><p>我们在<code>test</code>目录下创建一个测试类，如下所示：<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line">@RunWith(SpringRunner.class)</span><br><span class="line">@SpringBootTest(classes = RabbitMqLazyProviderApplication.class)</span><br><span class="line">public class RabbitMqLazyProviderApplicationTests &#123;</span><br><span class="line">    /**</span><br><span class="line">     * 消息队列提供者</span><br><span class="line">     */</span><br><span class="line">    @Autowired</span><br><span class="line">    private MessageProvider messageProvider;</span><br><span class="line"></span><br><span class="line">    /**</span><br><span class="line">     * 测试延迟消息消费</span><br><span class="line">     */</span><br><span class="line">    @Test</span><br><span class="line">    public void testLazy() &#123;</span><br><span class="line">        // 测试延迟10秒</span><br><span class="line">        messageProvider.sendMessage(&quot;测试延迟消费,写入时间：&quot; + new Date(),</span><br><span class="line">                QueueEnum.MESSAGE_TTL_QUEUE.getExchange(),</span><br><span class="line">                QueueEnum.MESSAGE_TTL_QUEUE.getRouteKey(),</span><br><span class="line">                10000);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></p>
<blockquote>
<p>注意：<code>@SpringBootTest</code>注解内添加了<code>classes</code>入口类的配置，因为我们是模块创建的项目并不是默认创建的<code>SpringBoot</code>项目，这里需要配置入口程序类才可以运行测试。</p>
</blockquote>
<p>在测试类我们注入了<code>MessageProvider</code>消息提供者，调用<code>sendMessage</code>方法发送消息到<code>消息通知延迟队列</code>，并且设置延迟的时间为<code>10秒</code>，这里衡量发送到指定队列的标准是要看<code>MessageRabbitMqConfiguration</code>配置类内的相关<code>Binding</code>配置，通过<code>Exchange</code>、<code>RouterKey</code>值进行发送到指定的队列。</p>
<p>到目前为止我们的<code>rabbitmq-lazy-provider</code>消息提供模块已经编写完成了，下面我们来看看消息消费者模块。</p>
<h3 id="队列消息消费者"><a href="#队列消息消费者" class="headerlink" title="队列消息消费者"></a>队列消息消费者</h3><p>我们再来创建一个名为<code>rabbitmq-lazy-consumer</code>的模块(Create New Maven Module)，同样需要在<code>pom.xml</code>配置文件内添加<code>rabbitmq-common</code>模块的依赖，如下所示：<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">&lt;!--添加公共模块依赖--&gt;</span><br><span class="line">&lt;dependency&gt;</span><br><span class="line">      &lt;groupId&gt;com.hengyu&lt;/groupId&gt;</span><br><span class="line">      &lt;artifactId&gt;rabbitmq-common&lt;/artifactId&gt;</span><br><span class="line">      &lt;version&gt;0.0.1-SNAPSHOT&lt;/version&gt;</span><br><span class="line">&lt;/dependency&gt;</span><br></pre></td></tr></table></figure></p>
<p>当然同样需要在<code>resource</code>下创建<code>application.yml</code>并添加消息队列的相关配置，代码就不贴出来了，可以直接从<code>rabbitmq-lazy-provider</code>模块中复制<code>application.yml</code>文件到当前模块内。</p>
<h4 id="消息消费者类"><a href="#消息消费者类" class="headerlink" title="消息消费者类"></a>消息消费者类</h4><p>接下来创建一个名为<code>MessageConsumer</code>的消费者类，该类需要监听<code>消息通知队列</code>，代码如下所示：<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line">/**</span><br><span class="line"> * 消息通知 - 消费者</span><br><span class="line"> *</span><br><span class="line"> * @author：于起宇 &lt;br/&gt;</span><br><span class="line"> * ===============================</span><br><span class="line"> * Created with IDEA.</span><br><span class="line"> * Date：2018/3/3</span><br><span class="line"> * Time：下午5:00</span><br><span class="line"> * 简书：http://www.jianshu.com/u/092df3f77bca</span><br><span class="line"> * ================================</span><br><span class="line"> */</span><br><span class="line">@Component</span><br><span class="line">@RabbitListener(queues = &quot;message.center.create&quot;)</span><br><span class="line">public class MessageConsumer &#123;</span><br><span class="line">    /**</span><br><span class="line">     * logger instance</span><br><span class="line">     */</span><br><span class="line">    static Logger logger = LoggerFactory.getLogger(MessageConsumer.class);</span><br><span class="line"></span><br><span class="line">    @RabbitHandler</span><br><span class="line">    public void handler(String content) &#123;</span><br><span class="line">        logger.info(&quot;消费内容：&#123;&#125;&quot;, content);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></p>
<p>在<code>@RabbitListener</code>注解内配置了监听的队列，这里配置内容是<code>QueueEnum</code>枚举内的<code>queueName</code>属性值，当然如果你采用常量的方式在注解属性上是直接可以使用的，枚举不支持这种配置，这里只能把<code>QueueName</code>字符串配置到<code>queues</code>属性上了。<br>由于我们在消息发送时采用字符串的形式发送消息内容，这里在<code>@RabbitHandler</code>处理方法的参数内要保持数据类型一致！</p>
<h4 id="消费者入口类"><a href="#消费者入口类" class="headerlink" title="消费者入口类"></a>消费者入口类</h4><p>我们为消费者模块添加一个入口程序类，用于启动消费者，代码如下所示：<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line">/**</span><br><span class="line"> * 【第四十六章：SpringBoot &amp; RabbitMQ完成消息延迟消费】</span><br><span class="line"> * 队列消费者模块 - 入口程序类</span><br><span class="line"> *</span><br><span class="line"> * @author：于起宇 &lt;br/&gt;</span><br><span class="line"> * ===============================</span><br><span class="line"> * Created with IDEA.</span><br><span class="line"> * Date：2018/3/3</span><br><span class="line"> * Time：下午4:55</span><br><span class="line"> * 简书：http://www.jianshu.com/u/092df3f77bca</span><br><span class="line"> * ================================</span><br><span class="line"> */</span><br><span class="line">@SpringBootApplication</span><br><span class="line">public class RabbitMqLazyConsumerApplication &#123;</span><br><span class="line"></span><br><span class="line">    public static void main(String[] args) &#123;</span><br><span class="line">        SpringApplication.run(RabbitMqLazyConsumerApplication.class, args);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></p>
<h1 id="测试"><a href="#测试" class="headerlink" title="测试"></a>测试</h1><p>我们的代码已经编写完毕，下面来测试下是否完成了我们预想的效果，步骤如下所示：<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">1. 启动消费者模块</span><br><span class="line">2. 执行RabbitMqLazyProviderApplicationTests.testLazy()方法进行发送消息到通知延迟队列</span><br><span class="line">3. 查看消费者模块控制台输出内容</span><br></pre></td></tr></table></figure></p>
<p>我们可以在消费者模块控制台看到输出内容：<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">2018-03-04 10:10:34.765  INFO 70486 --- [cTaskExecutor-1] c.h.r.lazy.consumer.MessageConsumer      : 消费内容：测试延迟消费,写入时间：Sun Mar 04 10:10:24 CST 2018</span><br></pre></td></tr></table></figure></p>
<p>我们在提供者测试方法发送消息的时间为<code>10:10:24</code>，而真正消费的时间则为<code>10:10:34</code>，与我们预计的一样，消息延迟了<code>10秒</code>后去执行消费。</p>
<h1 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h1><p>终上所述我们完成了消息队列的<code>延迟消费</code>，采用<code>死信</code>方式，通过消息过期方式触发，在实际项目研发过程中，延迟消费还是很有必要的，可以省去一些定时任务的配置。</p>
<p>本章源码已经上传到码云：<br>SpringBoot配套源码地址：<a href="https://gitee.com/hengboy/spring-boot-chapter" target="_blank" rel="noopener">https://gitee.com/hengboy/spring-boot-chapter</a><br>SpringCloud配套源码地址：<a href="https://gitee.com/hengboy/spring-cloud-chapter" target="_blank" rel="noopener">https://gitee.com/hengboy/spring-cloud-chapter</a><br>SpringBoot相关系列文章请访问：<a href="http://www.jianshu.com/p/9a08417e4e84" target="_blank" rel="noopener">目录：SpringBoot学习目录</a><br>QueryDSL相关系列文章请访问：<a href="http://www.jianshu.com/p/99a5ec5c3bd5" target="_blank" rel="noopener">QueryDSL通用查询框架学习目录</a><br>SpringDataJPA相关系列文章请访问：<a href="http://www.jianshu.com/p/615ed9c1fe84" target="_blank" rel="noopener">目录：SpringDataJPA学习目录</a>，感谢阅读！<br>欢迎加入QQ技术交流群，共同进步。<br><img src="http://upload-images.jianshu.io/upload_images/4461954-d80b777ca38632ba.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt="QQ技术交流群"></p>

        
        </div>
        <footer class="article-footer">
            <div class="share-container">


    <div class="bdsharebuttonbox">
    <a href="#" class="bds_more" data-cmd="more">分享到：</a>
    <a href="#" class="bds_qzone" data-cmd="qzone" title="分享到QQ空间">QQ空间</a>
    <a href="#" class="bds_tsina" data-cmd="tsina" title="分享到新浪微博">新浪微博</a>
    <a href="#" class="bds_tqq" data-cmd="tqq" title="分享到腾讯微博">腾讯微博</a>
    <a href="#" class="bds_renren" data-cmd="renren" title="分享到人人网">人人网</a>
    <a href="#" class="bds_weixin" data-cmd="weixin" title="分享到微信">微信</a>
</div>
<script>
window._bd_share_config={"common":{"bdSnsKey":{},"bdText":"","bdMini":"2","bdMiniList":false,"bdPic":"","bdStyle":"0","bdSize":"16"},"share":{"bdSize":16}};with(document)0[(getElementsByTagName('head')[0]||body).appendChild(createElement('script')).src='http://bdimg.share.baidu.com/static/api/js/share.js?v=89860593.js?cdnversion='+~(-new Date()/36e5)];
</script>
<style>
    .bdshare_popup_box {
        border-radius: 4px;
        border: #e1e1e1 solid 1px;
    }
    .bdshare-button-style0-16 a,
    .bdshare-button-style0-16 .bds_more {
        padding-left: 20px;
        margin: 6px 10px 6px 0;
    }
    .bdshare_dialog_list a,
    .bdshare_popup_list a,
    .bdshare_popup_bottom a {
        font-family: 'Microsoft Yahei';
    }
    .bdshare_popup_top {
        display: none;
    }
    .bdshare_popup_bottom {
        height: auto;
        padding: 5px;
    }
</style>


</div>

            
    

        </footer>
    </div>
    
        
<nav id="article-nav">
    
        <a href="/spring-boot-chapter-47/" id="article-nav-newer" class="article-nav-link-wrap">
            <strong class="article-nav-caption">上一篇</strong>
            <div class="article-nav-title">
                
                    第四十七章：SpringBoot2.0新特性 - Quartz自动化配置集成
                
            </div>
        </a>
    
    
        <a href="/spring-boot-chapter-45/" id="article-nav-older" class="article-nav-link-wrap">
            <strong class="article-nav-caption">下一篇</strong>
            <div class="article-nav-title">第四十五章：基于SpringBoot 设计业务逻辑异常统一处理</div>
        </a>
    
</nav>


    
</article>


    
    

</section>
            
			
				
<aside id="sidebar">
   
        
    <div class="widget-wrap">
        <h3 class="widget-title">最新文章</h3>
        <div class="widget">
            <ul id="recent-post" class="no-thumbnail">
                
                    <li>
                        
                        <div class="item-inner">
                            <p class="item-category"><a class="article-category-link" href="/categories/SpringBoot-核心技术/">SpringBoot 核心技术</a></p>
                            <p class="item-title"><a href="/spring-boot-chapter-52/" class="title">第五十二章：基于SpringBoot2使用Rest访问MongoDB数据</a></p>
                            <p class="item-date"><time datetime="2018-04-21T16:00:00.000Z" itemprop="datePublished">2018-04-22</time></p>
                        </div>
                    </li>
                
                    <li>
                        
                        <div class="item-inner">
                            <p class="item-category"><a class="article-category-link" href="/categories/SpringBoot-核心技术/">SpringBoot 核心技术</a></p>
                            <p class="item-title"><a href="/spring-boot-chapter-51/" class="title">第五十一章：基于SpringBoot2 &amp; MongoDB完成自动化集成</a></p>
                            <p class="item-date"><time datetime="2018-04-15T16:00:00.000Z" itemprop="datePublished">2018-04-16</time></p>
                        </div>
                    </li>
                
                    <li>
                        
                        <div class="item-inner">
                            <p class="item-category"><a class="article-category-link" href="/categories/SpringBoot-核心技术/">SpringBoot 核心技术</a></p>
                            <p class="item-title"><a href="/spring-boot-chapter-50/" class="title">第五十章：SpringBoot2.0新特性 - 岂止至今最简单redis缓存集成</a></p>
                            <p class="item-date"><time datetime="2018-04-14T16:00:00.000Z" itemprop="datePublished">2018-04-15</time></p>
                        </div>
                    </li>
                
                    <li>
                        
                        <div class="item-inner">
                            <p class="item-category"><a class="article-category-link" href="/categories/SpringBoot-核心技术/">SpringBoot 核心技术</a></p>
                            <p class="item-title"><a href="/spring-boot-chapter-49/" class="title">第四十九章：SpringBoot2.0新特性 - 你get到WebMvcConfigurer两种配置方式了吗？</a></p>
                            <p class="item-date"><time datetime="2018-03-16T16:00:00.000Z" itemprop="datePublished">2018-03-17</time></p>
                        </div>
                    </li>
                
                    <li>
                        
                        <div class="item-inner">
                            <p class="item-category"><a class="article-category-link" href="/categories/SpringBoot-核心技术/">SpringBoot 核心技术</a></p>
                            <p class="item-title"><a href="/spring-boot-chapter-48/" class="title">第四十八章：SpringBoot2.0新特性 - RabbitMQ信任package设置</a></p>
                            <p class="item-date"><time datetime="2018-03-12T16:00:00.000Z" itemprop="datePublished">2018-03-13</time></p>
                        </div>
                    </li>
                
            </ul>
        </div>
    </div>

    
        
    <div class="widget-wrap">
        <h3 class="widget-title">分类</h3>
        <div class="widget">
            <ul class="category-list"><li class="category-list-item"><a class="category-list-link" href="/categories/QueryDSL-核心技术/">QueryDSL 核心技术</a><span class="category-list-count">7</span></li><li class="category-list-item"><a class="category-list-link" href="/categories/SpringBoot-核心技术/">SpringBoot 核心技术</a><span class="category-list-count">36</span></li></ul>
        </div>
    </div>

    
        
    <div class="widget-wrap">
        <h3 class="widget-title">归档</h3>
        <div class="widget">
            <ul class="archive-list"><li class="archive-list-item"><a class="archive-list-link" href="/archives/2018/04/">四月 2018</a><span class="archive-list-count">3</span></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2018/03/">三月 2018</a><span class="archive-list-count">4</span></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2018/01/">一月 2018</a><span class="archive-list-count">1</span></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2017/12/">十二月 2017</a><span class="archive-list-count">4</span></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2017/11/">十一月 2017</a><span class="archive-list-count">2</span></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2017/10/">十月 2017</a><span class="archive-list-count">2</span></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2017/09/">九月 2017</a><span class="archive-list-count">4</span></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2017/08/">八月 2017</a><span class="archive-list-count">4</span></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2017/07/">七月 2017</a><span class="archive-list-count">9</span></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2017/06/">六月 2017</a><span class="archive-list-count">2</span></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2017/05/">五月 2017</a><span class="archive-list-count">3</span></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2017/04/">四月 2017</a><span class="archive-list-count">5</span></li></ul>
        </div>
    </div>

    
        
    <div class="widget-wrap">
        <h3 class="widget-title">标签</h3>
        <div class="widget">
            <ul class="tag-list"><li class="tag-list-item"><a class="tag-list-link" href="/tags/QueryDSL/">QueryDSL</a><span class="tag-list-count">7</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/SpringBoot/">SpringBoot</a><span class="tag-list-count">43</span></li></ul>
        </div>
    </div>

    
        
    <div class="widget-wrap">
        <h3 class="widget-title">标签云</h3>
        <div class="widget tagcloud">
            <a href="/tags/QueryDSL/" style="font-size: 10px;">QueryDSL</a> <a href="/tags/SpringBoot/" style="font-size: 20px;">SpringBoot</a>
        </div>
    </div>

    
        
    <div class="widget-wrap widget-list">
        <h3 class="widget-title">链接</h3>
        <div class="widget">
            <ul>
                
                    <li>
     				<a href="http://hexo.io" target="_blank">Hexo</a>
					</li>
                
            </ul>
        </div>
    </div>


    
    <div id="toTop" class="fa fa-angle-up"></div>
</aside>

				
        </div>
        <!--引入不蒜子-->
<script async src="//dn-lbstatics.qbox.me/busuanzi/2.3/busuanzi.pure.mini.js"></script>
<footer id="footer">
    <div class="outer">
        <div id="footer-info" class="inner">
            <span  id="busuanzi_container_site_pv">本站总访问量<span id="busuanzi_value_site_pv"></span>次</span>
            &copy; 2017 - 2018 恒宇少年 - 版权所有<br>
        </div>
    </div>
</footer>

        


    
        <script src="/libs/lightgallery/js/lightgallery.min.js"></script>
        <script src="/libs/lightgallery/js/lg-thumbnail.min.js"></script>
        <script src="/libs/lightgallery/js/lg-pager.min.js"></script>
        <script src="/libs/lightgallery/js/lg-autoplay.min.js"></script>
        <script src="/libs/lightgallery/js/lg-fullscreen.min.js"></script>
        <script src="/libs/lightgallery/js/lg-zoom.min.js"></script>
        <script src="/libs/lightgallery/js/lg-hash.min.js"></script>
        <script src="/libs/lightgallery/js/lg-share.min.js"></script>
        <script src="/libs/lightgallery/js/lg-video.min.js"></script>
    
    
        <script src="/libs/justified-gallery/jquery.justifiedGallery.min.js"></script>
    
    



<!-- Custom Scripts -->
<script src="/js/main.js"></script>

    </div>
</body>
</html>